package com.ruoyi.web.controller.admin.contract;

import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.dto.ContractPaymentScheduleCreateDTO;
import com.ruoyi.system.dto.ContractPaymentScheduleDTO;
import com.ruoyi.system.dto.ContractPaymentScheduleUpdateDTO;
import com.ruoyi.system.service.ContractPaymentScheduleService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;

/**
 * 合同付款周期管理控制器
 */
@Slf4j
@RestController
@RequestMapping("/admin/contracts/payment-schedules")
@RequiredArgsConstructor
@Api(tags = "合同付款周期管理")
public class ContractPaymentScheduleController extends BaseController {

    @Resource
    private ContractPaymentScheduleService paymentScheduleService;

    /**
     * 根据合同ID获取付款周期列表
     */
    @GetMapping("/contract/{contractId}")
    @ApiOperation("根据合同ID获取付款周期列表")
    public AjaxResult getByContractId(@PathVariable Long contractId) {
        try {
            List<ContractPaymentScheduleDTO> schedules = paymentScheduleService.getByContractId(contractId);
            return AjaxResult.success("查询成功", schedules);
        } catch (Exception e) {
            log.error("查询合同付款周期列表失败，合同ID: {}", contractId, e);
            return AjaxResult.error("查询失败：" + e.getMessage());
        }
    }

    /**
     * 创建付款周期
     */
    @PostMapping("/create")
    @ApiOperation("创建付款周期")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult create(@RequestBody @Valid ContractPaymentScheduleCreateDTO dto) {
        try {
            ContractPaymentScheduleDTO result = paymentScheduleService.create(dto);
            return AjaxResult.success("付款周期创建成功", result);
        } catch (Exception e) {
            log.error("创建付款周期失败，合同ID: {}, 分期: {}", dto.getContractId(), dto.getInstallment(), e);
            return AjaxResult.error("创建失败：" + e.getMessage());
        }
    }

    /**
     * 批量创建付款周期
     */
    @PostMapping("/createBatch")
    @ApiOperation("批量创建付款周期")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult createBatch(@RequestBody @Valid List<ContractPaymentScheduleCreateDTO> dtos) {
        try {
            List<ContractPaymentScheduleDTO> results = paymentScheduleService.createBatch(dtos);
            return AjaxResult.success("批量创建付款周期成功", results);
        } catch (Exception e) {
            log.error("批量创建付款周期失败", e);
            return AjaxResult.error("批量创建失败：" + e.getMessage());
        }
    }

    /**
     * 更新付款周期
     */
    @PutMapping("/update")
    @ApiOperation("更新付款周期")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult update(@RequestBody @Valid ContractPaymentScheduleUpdateDTO dto) {
        try {
            ContractPaymentScheduleDTO result = paymentScheduleService.update(dto);
            return AjaxResult.success("付款周期更新成功", result);
        } catch (Exception e) {
            log.error("更新付款周期失败，ID: {}", dto.getId(), e);
            return AjaxResult.error("更新失败：" + e.getMessage());
        }
    }

    /**
     * 删除付款周期
     */
    @DeleteMapping("/delete/{id}")
    @ApiOperation("删除付款周期")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult deleteById(@PathVariable Long id) {
        try {
            boolean result = paymentScheduleService.deleteById(id);
            return AjaxResult.success("付款周期删除成功", result);
        } catch (Exception e) {
            log.error("删除付款周期失败，ID: {}", id, e);
            return AjaxResult.error("删除失败：" + e.getMessage());
        }
    }

    /**
     * 根据合同ID删除所有付款周期
     */
    @DeleteMapping("/deleteByContract/{contractId}")
    @ApiOperation("根据合同ID删除所有付款周期")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult deleteByContractId(@PathVariable Long contractId) {
        try {
            boolean result = paymentScheduleService.deleteByContractId(contractId);
            return AjaxResult.success("合同付款周期删除成功", result);
        } catch (Exception e) {
            log.error("删除合同付款周期失败，合同ID: {}", contractId, e);
            return AjaxResult.error("删除失败：" + e.getMessage());
        }
    }

    /**
     * 更新付款状态
     */
    @PostMapping("/updatePaymentStatus")
    @ApiOperation("更新付款状态")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult updatePaymentStatus(@RequestParam Long id,
                                        @RequestParam Integer paymentStatus,
                                        @RequestParam(required = false) LocalDate actualPaymentDate,
                                        @RequestParam(required = false) BigDecimal actualPaymentAmount) {
        try {
            boolean result = paymentScheduleService.updatePaymentStatus(id, paymentStatus, 
                    actualPaymentDate, actualPaymentAmount);
            return AjaxResult.success("付款状态更新成功", result);
        } catch (Exception e) {
            log.error("更新付款状态失败，ID: {}", id, e);
            return AjaxResult.error("更新失败：" + e.getMessage());
        }
    }

    /**
     * 统计合同的总付款金额
     */
    @GetMapping("/totalPaymentAmount/{contractId}")
    @ApiOperation("统计合同的总付款金额")
    public AjaxResult getTotalPaymentAmount(@PathVariable Long contractId) {
        try {
            BigDecimal totalAmount = paymentScheduleService.getTotalPaymentAmount(contractId);
            return AjaxResult.success("查询成功", totalAmount);
        } catch (Exception e) {
            log.error("统计合同总付款金额失败，合同ID: {}", contractId, e);
            return AjaxResult.error("查询失败：" + e.getMessage());
        }
    }

    /**
     * 统计合同的总已付款金额
     */
    @GetMapping("/totalActualPaymentAmount/{contractId}")
    @ApiOperation("统计合同的总已付款金额")
    public AjaxResult getTotalActualPaymentAmount(@PathVariable Long contractId) {
        try {
            BigDecimal totalAmount = paymentScheduleService.getTotalActualPaymentAmount(contractId);
            return AjaxResult.success("查询成功", totalAmount);
        } catch (Exception e) {
            log.error("统计合同总已付款金额失败，合同ID: {}", contractId, e);
            return AjaxResult.error("查询失败：" + e.getMessage());
        }
    }

    /**
     * 创建默认付款周期
     */
    @PostMapping("/createDefault/{contractId}")
    @ApiOperation("创建默认付款周期")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult createDefaultPaymentSchedules(@PathVariable Long contractId,
                                                  @RequestParam BigDecimal totalAmount) {
        try {
            List<ContractPaymentScheduleDTO> results = paymentScheduleService.createDefaultPaymentSchedules(contractId, totalAmount);
            return AjaxResult.success("默认付款周期创建成功", results);
        } catch (Exception e) {
            log.error("创建默认付款周期失败，合同ID: {}, 总金额: {}", contractId, totalAmount, e);
            return AjaxResult.error("创建失败：" + e.getMessage());
        }
    }

    /**
     * 获取付款方式选项
     */
    @GetMapping("/paymentMethods")
    @ApiOperation("获取付款方式选项")
    public AjaxResult getPaymentMethods() {
        try {
            List<Map<String, Object>> methods = new ArrayList<>();
            methods.add(createOption(1, "现金"));
            methods.add(createOption(2, "银行转账"));
            methods.add(createOption(3, "支票"));
            methods.add(createOption(4, "其他"));
            return AjaxResult.success("查询成功", methods);
        } catch (Exception e) {
            log.error("获取付款方式选项失败", e);
            return AjaxResult.error("查询失败：" + e.getMessage());
        }
    }

    /**
     * 获取付款状态选项
     */
    @GetMapping("/paymentStatuses")
    @ApiOperation("获取付款状态选项")
    public AjaxResult getPaymentStatuses() {
        try {
            List<Map<String, Object>> statuses = new ArrayList<>();
            statuses.add(createOption(0, "未付款"));
            statuses.add(createOption(1, "已付款"));
            statuses.add(createOption(2, "部分付款"));
            statuses.add(createOption(3, "逾期"));
            return AjaxResult.success("查询成功", statuses);
        } catch (Exception e) {
            log.error("获取付款状态选项失败", e);
            return AjaxResult.error("查询失败：" + e.getMessage());
        }
    }

    /**
     * 创建选项对象
     */
    private Map<String, Object> createOption(Integer value, String label) {
        Map<String, Object> option = new HashMap<>();
        option.put("value", value);
        option.put("label", label);
        return option;
    }
}
